﻿using Mbs.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.Json;

namespace Mbs.Utils
{
    public static class LicenseManager<T>
    {
        private const int KeySize = 2048;
        private const int FormatVersion = 1;
        /// <summary>
        /// 生成RSA密钥对
        /// </summary>
        public static (string publicKey, string privateKey) GenerateKeys()
        {
            using var rsa = RSA.Create(KeySize);
            return (
                rsa.ExportRSAPublicKeyPem(),
                rsa.ExportRSAPrivateKeyPem()
            );
        }
        /// <summary>
        /// 生成许可证文件
        /// </summary>
        /// <param name="data">许可证数据对象</param>
        /// <param name="privateKeyPem">私钥PEM格式</param>
        /// <param name="hmacSecret">HMAC加密密钥</param>
        public static string Generate(T data, string privateKeyPem, string hmacSecret)
        {
            // 序列化数据
            var jsonData = JsonSerializer.SerializeToUtf8Bytes(data);

            // 计算HMAC
            using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(hmacSecret));
            var hmacHash = hmac.ComputeHash(jsonData);
            // 构建数据包
            var dataPackage = BuildDataPackage(jsonData, hmacHash);
            // RSA签名
            using var rsa = RSA.Create();
            rsa.ImportFromPem(privateKeyPem);
            var signature = rsa.SignData(dataPackage, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
            // 最终打包
            return BuildFinalPackage(dataPackage, signature);
        }
        /// <summary>
        /// 验证许可证文件
        /// </summary>
        /// <param name="licenseString">许可证字符串</param>
        /// <param name="publicKeyPem">公钥PEM格式</param>
        /// <param name="hmacSecret">HMAC加密密钥</param>
        public static T Validate(string licenseString, string publicKeyPem, string hmacSecret)
        {
            var (dataPackage, signature) = ParseLicenseString(licenseString);
            // 验证签名
            using var rsa = RSA.Create();
            rsa.ImportFromPem(publicKeyPem);
            if (!rsa.VerifyData(dataPackage, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1))
            {
                throw new LicenseValidationException("数字签名验证失败");
            }
            // 解析数据包
            var (jsonData, storedHmac) = ParseDataPackage(dataPackage);
            // 验证HMAC
            using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(hmacSecret));
            var computedHmac = hmac.ComputeHash(jsonData);
            if (!computedHmac.SequenceEqual(storedHmac))
            {
                throw new LicenseValidationException("数据完整性校验失败");
            }
            return JsonSerializer.Deserialize<T>(jsonData) ?? throw new LicenseValidationException("反序列化失败");
        }
        #region Helper Methods
        private static byte[] BuildDataPackage(byte[] jsonData, byte[] hmacHash)
        {
            using var ms = new MemoryStream();
            using (var writer = new BinaryWriter(ms, Encoding.UTF8, true))
            {
                writer.Write(FormatVersion);         // 版本号
                writer.Write(DateTime.UtcNow.Ticks); // 时间戳
                writer.Write(jsonData.Length);
                writer.Write(jsonData);
                writer.Write(hmacHash.Length);
                writer.Write(hmacHash);
            }
            return ms.ToArray();
        }
        private static string BuildFinalPackage(byte[] dataPackage, byte[] signature)
        {
            using var ms = new MemoryStream();
            using (var writer = new BinaryWriter(ms, Encoding.UTF8, true))
            {
                writer.Write(dataPackage.Length);
                writer.Write(dataPackage);
                writer.Write(signature.Length);
                writer.Write(signature);
            }
            return Convert.ToBase64String(ms.ToArray());
        }
        private static (byte[] dataPackage, byte[] signature) ParseLicenseString(string licenseString)
        {
            try
            {
                var fullPackage = Convert.FromBase64String(licenseString);
                using var stream = new MemoryStream(fullPackage);
                using var reader = new BinaryReader(stream);
                var dataLength = reader.ReadInt32();
                var dataPackage = reader.ReadBytes(dataLength);
                var signatureLength = reader.ReadInt32();
                var signature = reader.ReadBytes(signatureLength);
                return (dataPackage, signature);
            }
            catch (Exception ex)
            {
                throw new LicenseValidationException("许可证格式错误", ex);
            }
        }
        private static (byte[] jsonData, byte[] hmacHash) ParseDataPackage(byte[] dataPackage)
        {
            try
            {
                using var stream = new MemoryStream(dataPackage);
                using var reader = new BinaryReader(stream);
                var version = reader.ReadInt32();
                if (version != FormatVersion) throw new LicenseValidationException("不支持的版本格式");
                _ = reader.ReadInt64(); // 跳过时间戳
                var jsonLength = reader.ReadInt32();
                var jsonData = reader.ReadBytes(jsonLength);
                var hmacLength = reader.ReadInt32();
                var hmacHash = reader.ReadBytes(hmacLength);
                return (jsonData, hmacHash);
            }
            catch (Exception ex)
            {
                throw new LicenseValidationException("数据包解析失败", ex);
            }
        }
        #endregion
        /// <summary>
        /// 文件操作扩展方法
        /// </summary>
        public static class FileOperations
        {
            public static void SaveToFile(string licenseString, string filePath)
                => File.WriteAllText(filePath, licenseString);
            public static T LoadFromFile(string filePath, string publicKeyPem, string hmacSecret)
                => Validate(File.ReadAllText(filePath), publicKeyPem, hmacSecret);
        }
        public class LicenseValidationException : Exception
        {
            public LicenseValidationException(string message) : base(message) { }
            public LicenseValidationException(string message, Exception inner) : base(message, inner) { }
        }
    }
}


//// 生成密钥对（非泛型）
//(string pubKey, string priKey) = LicenseManager<MyLicense>.GenerateKeys();

//// 生成许可证
//var licenseStr = LicenseManager<MyLicense>.Generate(
//data: myData,
//    privateKeyPem: privateKey,
//    hmacSecret: "自定义密钥");

//// 验证许可证
//var data = LicenseManager<MyLicense>.Validate(
//    licenseString: licenseStr,
//    publicKeyPem: publicKey,
//    hmacSecret: "自定义密钥");

// 自定义数据类型

//public class MyLicense
//{
//    public string MachineCode { get; set; }
//    public DateTime ExpireDate { get; set; }
//    public Dictionary<string, object> Features { get; set; }
//}

//// 生成示例
//var myData = new MyLicense
//{
//    MachineCode = "ABC-123",
//    ExpireDate = DateTime.Now.AddYears(1),
//    Features = new Dictionary<string, object> { ["Premium"] = true }
//};

//var (publicKey, privateKey) = LicenseManager<MyLicense>.GenerateKeys();
//var license = LicenseManager<MyLicense>.Generate(myData, privateKey, "secret123");

//// 验证示例
//try
//{
//    var validatedData = LicenseManager<MyLicense>.Validate(license, publicKey, "secret123");

//    // 自定义业务验证
//    if (validatedData.ExpireDate < DateTime.Now)
//        throw new Exception("许可证已过期");

//    if (validatedData.MachineCode != currentMachineCode)
//        throw new Exception("机器码不匹配");
//}
//catch (LicenseManager<MyLicense>.LicenseValidationException ex)
//{
//    // 处理验证失败
//}
